using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.IO;
using System.Text.RegularExpressions;
using System.Windows.Forms;

namespace PicViewer
{
    class ImageViewer : Form
    {
        private TextBox m_textboxPath;
        private Image m_imagePainter;
        private Panel m_picPanel;
        private Panel m_funcButtonsPanel;
        private float m_scaleFactor = 1.0f; 
        private const string C_ImgExtensionRegx = @"\.(jpg|jpeg|png|gif)$";
        
        public ImageViewer(string[] args)
        {
            var savepath = Path.Combine(Application.CommonAppDataPath, "cfg.txt");
            this.WindowState = FormWindowState.Maximized;
            //this.DoubleBuffered = true;
            m_funcButtonsPanel = new FlowLayoutPanel()
            {
                Parent = this,
                Location = new Point(0, 0),
                Size = new Size(800, 30),
                FlowDirection = FlowDirection.LeftToRight,
            };

            var cbLeftRightMode = new CheckBox()
            {
                Parent = m_funcButtonsPanel,
                Text = "左右键交换",
                Size = new Size(100, 25),
                Checked = false,
            };

            if (File.Exists(savepath))
            {
                cbLeftRightMode.Checked = bool.Parse(File.ReadAllText(savepath));
            }
            Application.ApplicationExit += (ss, se) => File.WriteAllText(savepath, cbLeftRightMode.Checked.ToString());

            var lb = new Label()
            {
                Parent = m_funcButtonsPanel,
                Text = "目录：",
                TextAlign = ContentAlignment.MiddleCenter,
                Size = new Size(50, 30),
            };

            m_textboxPath = new TextBox()
            {
                Parent = m_funcButtonsPanel,
                Size = new Size(450, 25),
            };

            var btnNextFolder = new Label()
            {
                Parent = m_funcButtonsPanel,
                Size = new Size(100, 25),
                Text = "切换目录↑↓",
                BackColor = Color.White,
                TextAlign = ContentAlignment.MiddleCenter,
                BorderStyle = BorderStyle.FixedSingle,
                Cursor = Cursors.Hand,
            };
            btnNextFolder.MouseEnter += (ss, se) =>
            {
                btnNextFolder.BackColor = Color.LimeGreen;
            };
            btnNextFolder.MouseLeave += (ss, se) =>
            {
                btnNextFolder.BackColor = Color.White;
            };

            btnNextFolder.MouseClick += (ss, se) =>
            {
                if (se.Button == MouseButtons.Left)
                {
                    LoadNextDirectory(Direction.Left);
                }
                else if (se.Button == MouseButtons.Right)
                {
                    LoadNextDirectory(Direction.Right);
                }
            };

            this.m_picPanel = new DPanel()
            {
                Parent = this,
                Dock = DockStyle.Fill,
                AutoScroll = true,
            };


            var pictureBoxViewer = m_picPanel;


            string filePath = args[0];
            if (args.Length > 1)
            {
                filePath = args[1];
                m_textboxPath.Text = Path.GetDirectoryName(filePath);

                //直接定位当前文件所属序号
                var fileList = GetAllImgs(filePath);
                string toLocate = Path.GetFileName(filePath);
                m_imgPathIndex = fileList.FindIndex((currP) => Path.GetFileName(currP) == toLocate) - 1;

                ViewNextImage(m_textboxPath, m_picPanel, true);
            }
            else
            {
                m_textboxPath.Text = Path.GetDirectoryName(filePath);
            }

            m_textboxPath.KeyDown += (ss, se) =>
            {
                if (se.KeyCode == Keys.Enter)
                {
                    GetAllImgsPath(m_textboxPath);

                    m_imgPathIndex = -1;
                    ViewNextImage(m_textboxPath, m_picPanel, true);
                }

            };

            this.KeyPreview = true;
            var isCtrlDown = false;
            this.KeyDown += (ss, se) =>
            {
                if (se.KeyCode == Keys.Right)
                {
                    ViewNextImage(m_textboxPath, pictureBoxViewer, true);

                }
                else if (se.KeyCode == Keys.Left)
                {
                    ViewNextImage(m_textboxPath, pictureBoxViewer, false);

                }
                else if (se.KeyCode == Keys.Up)
                {
                    //向上滚动
                    if (m_picPanel.VerticalScroll.Value > 25)
                    {
                        m_picPanel.VerticalScroll.Value -= 25;
                    }
                    else
                    {
                        m_picPanel.VerticalScroll.Value = m_picPanel.VerticalScroll.Minimum;
                    }

                }
                else if (se.KeyCode == Keys.Down)
                {
                    if (m_picPanel.VerticalScroll.Value < m_picPanel.VerticalScroll.Maximum - 25)
                    {
                        m_picPanel.VerticalScroll.Value += 25;
                    }
                    else
                    {
                        m_picPanel.VerticalScroll.Value = m_picPanel.VerticalScroll.Maximum;
                    }
                }
                else if (se.KeyCode == Keys.ControlKey)
                {
                    isCtrlDown = true;
                }
            };

            this.KeyUp += (ss, se) =>
            {
                if (se.KeyCode == Keys.ControlKey)
                {
                    isCtrlDown = false;
                }
            };

            pictureBoxViewer.MouseClick += (ss, se) =>
             {
                 if (se.Button == MouseButtons.Left)
                 {
                     //允许直接Ctrl+鼠标，用于切换目录
                     if (isCtrlDown)
                     {
                         LoadNextDirectory(cbLeftRightMode.Checked ? Direction.Right : Direction.Left);
                     }
                     else
                     {
                         ViewNextImage(m_textboxPath, pictureBoxViewer, cbLeftRightMode.Checked ? true : false);
                     }
                 }
                 else if (se.Button == MouseButtons.Right)
                 {
                     if (isCtrlDown)
                     {
                         LoadNextDirectory(cbLeftRightMode.Checked ? Direction.Left : Direction.Right);
                     }
                     else
                     {
                         ViewNextImage(m_textboxPath, pictureBoxViewer, cbLeftRightMode.Checked ? false : true);

                     }
                 }
                 else if (se.Button == MouseButtons.Middle)
                 {
                     m_funcButtonsPanel.Visible = !m_funcButtonsPanel.Visible;
                     if (m_funcButtonsPanel.Visible)
                     {
                         m_funcButtonsPanel.BringToFront();
                     }
                 }
             };

            pictureBoxViewer.Paint += PictureBox_Paint;
            pictureBoxViewer.MouseWheel += (ss, se) =>
            {
                //var loc = pictureBoxViewer.Location;
                //loc.Y += se.Delta / 12 * 3;
                //pictureBoxViewer.Location = loc;
                if ((ModifierKeys & Keys.Control) == Keys.Control)
                {
                    // 调整缩放比例
                    m_scaleFactor *= (se.Delta > 0 ? 1.1f : 0.9f);
                    m_scaleFactor = Math.Max(0.1f, Math.Min(10.0f, m_scaleFactor));

                    // 更新Panel的滚动范围
                    UpdateScrollRange();
                    // 刷新PictureBox以重新绘制
                    pictureBoxViewer.Invalidate();
                }
                else
                {
                    //滚动事件直接留给panel本身
                    //int units = se.Delta > 0 ? -3 : 3;
                    //panel.AutoScrollPosition = new Point(
                    //    panel.AutoScrollPosition.X,
                    //    panel.AutoScrollPosition.Y + units
                    //);

                }

            };

            Timer t = new Timer();
            t.Interval = 1000;
            t.Tick += (ss, se) =>
            {
                if (m_funcButtonsPanel.Visible)
                {
                    m_funcButtonsPanel.Visible = false;
                }

                t.Stop();
                t.Dispose();
                t = null;
            };
            t.Start();


        }

        private const int DeltaWidth = 20;
        private const int DeltaHeight = 20;

        private void PictureBox_Paint(object sender, PaintEventArgs e)
        {
            if (m_imagePainter == null)
            {
                return;
            }

            // 计算缩放后的尺寸
            int scaledWidth = (int)(m_imagePainter.Width * m_scaleFactor);
            int scaledHeight = (int)(m_imagePainter.Height * m_scaleFactor);

            // 计算偏移量
            int offsetX = m_picPanel.AutoScrollPosition.X;
            int offsetY = m_picPanel.AutoScrollPosition.Y;

            // 绘制图像
            e.Graphics.InterpolationMode = InterpolationMode.High;
            e.Graphics.DrawImage(m_imagePainter, new Rectangle(DeltaWidth + offsetX, DeltaHeight + offsetY, scaledWidth, scaledHeight));
        }

        private void UpdateScrollRange()
        {
            if (m_imagePainter == null)
            {
                return;
            }
            // 更新Panel的滚动范围以适应缩放后的图像
            m_picPanel.AutoScrollMinSize = new Size(
                (int)(m_imagePainter.Width * m_scaleFactor + DeltaWidth * 2),
                (int)(m_imagePainter.Height * m_scaleFactor + DeltaHeight * 2)
            );
        }

        // 获得指定文件夹的所有文件的全路径
        string[] m_imgPathArr = null;
        int m_imgPathIndex = 0;
        private void ViewNextImage(TextBox textBox1, Control pictureBox1, bool isNext)
        {
            try
            {
                if (m_imgPathArr == null || m_imgPathArr.Length == 0)
                {
                    GetAllImgsPath(textBox1);
                }
                if (m_imgPathArr == null || m_imgPathArr.Length == 0)
                {
                    return;
                }

                if (isNext)
                {
                    m_imgPathIndex++;
                    if (m_imgPathIndex >= m_imgPathArr.Length)
                    {
                        m_imgPathIndex = 0;
                    }
                }
                else
                {
                    m_imgPathIndex--;
                    if (m_imgPathIndex < 0)
                    {
                        m_imgPathIndex = m_imgPathArr.Length - 1;
                    }
                }

                if (m_imagePainter != null)
                {
                    m_imagePainter.Dispose();
                }

                m_imagePainter = Image.FromFile(m_imgPathArr[m_imgPathIndex]);
                this.Text = m_imgPathArr[m_imgPathIndex];
                m_funcButtonsPanel.Visible = false;
                //保留缩放比例
                //scaleFactor = 1.0f;
                m_picPanel.AutoScrollPosition = new Point(0, 0);
                UpdateScrollRange();
                pictureBox1.Invalidate();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        /// <summary>
        /// 读入目录下的所有的图片路径
        /// </summary>
        private void GetAllImgsPath(TextBox textBoxPath)
        {
            m_imgPathArr = GetAllImgs(textBoxPath.Text).ToArray();
        }

        /// <summary>
        /// 读入当前目录的下个目录
        /// </summary>
        /// <param name="direction"></param>
        private void LoadNextDirectory(Direction direction)
        {
            if (m_imgPathArr == null || m_imgPathArr.Length <= 0 || string.IsNullOrEmpty(m_imgPathArr[0]))
            {
                return;
            }

            //获得当前目录的上一目录
            string path = Path.GetDirectoryName(m_imgPathArr[0]);
            var dirInf = new DirectoryInfo(path);

            //最多往上挖掘3级目录
            var tryCount = 3;
            while (--tryCount > 0)
            {
                var dirParent = dirInf.Parent;
                if (dirParent.Root.FullName == dirParent.FullName)
                {
                    //拒绝载入，怕下属文件太多
                    return;
                }

                //邻居目录
                var neighborDirs = new List<DirectoryInfo>(dirParent.GetDirectories());

                var dictDir2File = new Dictionary<string, string>();

                //过滤出有效目录：
                neighborDirs = neighborDirs.FindAll((dir) =>
                  {
                      //目录里至少要有一个
                      var fileList = new List<FileInfo>(dir.GetFiles("*", SearchOption.AllDirectories));

                      var imgFile = fileList.Find((file) => Regex.IsMatch(file.Name, C_ImgExtensionRegx));
                      if (imgFile != null)
                      {
                          //记录一下映射
                          dictDir2File[dir.FullName] = imgFile.DirectoryName;
                          return true;
                      }
                      return false;
                  });

                //没有其他目录,找上一层目录
                if (neighborDirs.Count <= 1)
                {
                    dirInf = dirParent;
                    continue;
                }

                //找出当前目录  是父目录下的第几个目录
                int toDirIdx = -1;
                for (int i = 0; i < neighborDirs.Count; i++)
                {
                    if (neighborDirs[i].Name == dirInf.Name)
                    {
                        //找到
                        toDirIdx = i;
                        break;
                    }
                }

                if (toDirIdx >= 0)
                {
                    //再找下一个目录：
                    toDirIdx += direction == Direction.Left ? -1 : 1;
                    if (toDirIdx < 0)
                    {
                        toDirIdx = neighborDirs.Count - 1;
                    }
                    else if (toDirIdx >= neighborDirs.Count)
                    {
                        toDirIdx = 0;
                    }
                }

                //直接进入下一目录(此处目录可能是需要子目录）
                m_textboxPath.Text = dictDir2File[neighborDirs[toDirIdx].FullName];
                m_imgPathIndex = -1;
                m_imgPathArr = null;
                ViewNextImage(m_textboxPath, m_picPanel, true);

            }

        }

        private static List<string> GetAllImgs(string filePath)
        {
            //string tbPath = Path.GetDirectoryName(path);
            //不管输入的是文件名或者是目录名，都提取其目录
            string fileName = Path.GetFileName(filePath);
            if (!string.IsNullOrEmpty(fileName) && Regex.IsMatch(fileName, C_ImgExtensionRegx))
            {
                //这是一个文件名路径,需要获取其目录名
                filePath = Path.GetDirectoryName(filePath);
            }

            if (!Directory.Exists(filePath))
            {
                return new List<string>();
            }

            var allFiles = Directory.GetFiles(filePath);
            List<string> fileNames = new List<string>(allFiles);
            return fileNames.FindAll((str) => Regex.IsMatch(str, C_ImgExtensionRegx));
        }
    }

    /// <summary>
    /// 开启双重Buffer以更好渲染图片
    /// </summary>
    class DPanel : Panel
    {
        public DPanel()
        {
            DoubleBuffered = true;
        }
    }

    enum Direction { Left, Right }
}
